﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Web.UI.WebControls;
using umbraco;
using umbraco.BusinessLogic;
using umbraco.controls;
using umbraco.DataLayer;
using umbraco.uicontrols;
using umbraco.uicontrols.DatePicker;
using System.Web;

namespace tswe.log
{
    public partial class viewLog : System.Web.UI.UserControl
    {

        # region members

        protected ContentPicker cp;
        protected DateTimePicker datePicker;

        # endregion members

        protected void Page_Load(object sender, EventArgs e)
        {

        }

        protected override void OnInit(EventArgs e)
        {
            if (Parent is TabPage)
                InitControlItems();
            base.OnInit(e);
        }

        public void InitControlItems()
        {
            // hide result pane
            titlePane2.Visible = false;
            Pane2.Visible = false;

            // init menu buttons
            TabPage tp = this.Parent as TabPage;

            ImageButton search = tp.Menu.NewImageButton();
            search.ImageUrl = GlobalSettings.Path + "/plugins/tswe/log/images/search.png";
            search.CommandName = "search";
            search.AlternateText = "Search Log";
            search.Command += new CommandEventHandler(search_Command);

            cp = new ContentPicker();
            contentPlace.Controls.Add(cp);

            datePicker = new DateTimePicker();
            datePicker.ShowTime = false;
            datePicker.ID = "dpSinceDate";
            sincePlace.Controls.Add(datePicker);
            initDatePicker();


            // list all log types sorted
            List<String> logTypeNames = new List<String>();
            logTypeNames.AddRange(Enum.GetNames(typeof(LogTypes)));
            logTypeNames.Sort();

            ddlLogType.Items.Add(new ListItem("all", ""));

            foreach (string logTypeName in logTypeNames)
            {
                ListItem li = new ListItem(logTypeName, logTypeName);
                ddlLogType.Items.Add(li);
            }

            // list all users sorted
            SortedList<string, string> users = new SortedList<string, string>();
            foreach (User user in User.getAll())
            {
                users.Add(user.Name, user.Id.ToString());
            }
            
            ddlUser.Items.Add(new ListItem("all", "-1"));
            foreach (KeyValuePair<string, string> kvp in users)
            {
                ListItem li = new ListItem(kvp.Key, kvp.Value);
                ddlUser.Items.Add(li);
            }
        }

        private void initDatePicker()
        {
            datePicker.DateTime = DateTime.Now.AddMonths(-1);
        }

        void search_Command(object sender, CommandEventArgs e)
        {
            searchLog();
        }

        private void searchLog()
        {
            LogTypes logType = LogTypes.System;
            User user = null;

            // get search log parameters
            int days = int.Parse(rblSince.SelectedValue);

            if (days == 0)
            {
                if (datePicker.DateTime < new DateTime(2000, 01, 01))
                    initDatePicker();

                days = (DateTime.Now - datePicker.DateTime).Days;
            }

            DateTime sinceDate = DateTime.Now - new TimeSpan(days, 0, 0, 0);
            int userId = int.Parse(ddlUser.SelectedValue);

            if (userId != -1)
                user = new User(userId);
            int nodeId = -1;
            if (!String.IsNullOrEmpty(cp.Value))
                nodeId = int.Parse(cp.Value);
            bool auditTrail = cbxAuditTrail.Checked;
            string value = ddlLogType.SelectedValue;
            bool allLogTypes = false;
            if (String.IsNullOrEmpty(value))
                allLogTypes = true;
            else
                logType = (LogTypes)Enum.Parse(typeof(LogTypes), value);

            IRecordsReader reader = null;

            if (nodeId >= 0)
            {
                // Show result pane
                titlePane2.Visible = true;
                Pane2.Visible = true;

                if (auditTrail)
                    logGrid.DataSource = getNodeIdAuditLog(nodeId);
                else
                    logGrid.DataSource = getNodeIdLog(nodeId);
                logGrid.DataBind();
                return;
            }
            else if (allLogTypes)
            {
                if (user != null)
                    reader = Log.GetLogReader(user, sinceDate);
            }
            else if (userId == -1)
            {
                reader = Log.GetLogReader(logType, sinceDate);
            }
            else
                reader = Log.GetLogReader(user, logType, sinceDate);

            bool hasReader = (reader != null);
            if (!hasReader)
            {
                logGrid.DataSource = null;
            }
            else
                logGrid.DataSource = getLog(reader);
            logGrid.DataBind();

            // Show or hide result pane
            titlePane2.Visible = hasReader;
            Pane2.Visible = hasReader;
        }

        private ICollection getLog(IRecordsReader reader)
        {
            DataTable dt = new DataTable();
            DataRow dr;

            dt.Columns.Add(new DataColumn("logHeader", typeof(string)));
            dt.Columns.Add(new DataColumn("userId", typeof(int)));
            dt.Columns.Add(new DataColumn("nodeId", typeof(int)));
            dt.Columns.Add(new DataColumn("DateStamp", typeof(DateTime)));
            dt.Columns.Add(new DataColumn("logComment", typeof(string)));

            while (reader.Read())
            {
                dr = dt.NewRow();

                dr[0] = encode(reader.GetString("logHeader"));
                dr[1] = reader.GetInt("userId");
                dr[2] = reader.GetInt("nodeId");
                dr[3] = reader.GetDateTime("DateStamp");
                dr[4] = encode(reader.GetString("logComment"));

                dt.Rows.Add(dr);
            }
            reader.Close();

            DataView dv = new DataView(dt);
            return dv;
        }

        private static ISqlHelper sqlHelper
        {
            get { return umbraco.BusinessLogic.Application.SqlHelper; }
        }

        private string encode(string value)
        {
            return HttpUtility.HtmlEncode(value);
        }

        private ICollection getNodeIdLog(int nodeId)
        {
            IRecordsReader reader = sqlHelper.ExecuteReader(
                @"select userId, DateStamp, logHeader, logComment 
                from umbracoLog inner join umbracoUser u on u.id = userId 
                where nodeId = @id
                order by DateStamp desc",
                sqlHelper.CreateParameter("@id", nodeId));

            DataTable dt = new DataTable();
            DataRow dr;

            dt.Columns.Add(new DataColumn("logHeader", typeof(string)));
            dt.Columns.Add(new DataColumn("userId", typeof(int)));
            dt.Columns.Add(new DataColumn("nodeId", typeof(int)));
            dt.Columns.Add(new DataColumn("DateStamp", typeof(DateTime)));
            dt.Columns.Add(new DataColumn("logComment", typeof(string)));

            while (reader.Read())
            {
                dr = dt.NewRow();

                dr[0] = encode(reader.GetString("logHeader"));
                dr[1] = reader.GetInt("userId");
                dr[2] = nodeId;
                dr[3] = reader.GetDateTime("DateStamp");
                dr[4] = encode(reader.GetString("logComment"));

                dt.Rows.Add(dr);
            }
            reader.Close();

            DataView dv = new DataView(dt);
            return dv;
        }

        private ICollection getNodeIdAuditLog(int nodeId)
        {
            IRecordsReader reader = sqlHelper.ExecuteReader(
                @"select userId, logHeader, 
                DateStamp, logComment 
                from umbracoLog inner join umbracoUser u on u.id = userId 
                where nodeId = @id and logHeader not in ('open','system') 
                order by DateStamp desc",
                sqlHelper.CreateParameter("@id", nodeId));

            DataTable dt = new DataTable();
            DataRow dr;

            dt.Columns.Add(new DataColumn("logHeader", typeof(string)));
            dt.Columns.Add(new DataColumn("userId", typeof(int)));
            dt.Columns.Add(new DataColumn("nodeId", typeof(int)));
            dt.Columns.Add(new DataColumn("DateStamp", typeof(DateTime)));
            dt.Columns.Add(new DataColumn("logComment", typeof(string)));

            while (reader.Read())
            {
                dr = dt.NewRow();

                dr[0] = encode(reader.GetString("logHeader"));
                dr[1] = reader.GetInt("userId");
                dr[2] = nodeId;
                dr[3] = reader.GetDateTime("DateStamp");
                dr[4] = encode(reader.GetString("logComment"));

                dt.Rows.Add(dr);
            }
            reader.Close();

            DataView dv = new DataView(dt);
            return dv;
        }

        public string GetUserName(string userId)
        {
            User myUser = new User(int.Parse(userId));
            if (myUser == null || myUser.Name == null)
                return "(unknown)";
            return myUser.Name.ToString();
        }

        public string GetNodeName(string nodeId)
        {
            if (nodeId == null|| nodeId.Trim() == "" || nodeId == "-1")
                return "(none)";
            else
            {
                string url = library.NiceUrl(int.Parse(nodeId));
                if (String.IsNullOrEmpty(url))
                    return "(none)";
                else
                    return "<a href='" + url + "' target='_blank' >" 
                        + library.GetItem(int.Parse(nodeId), "nodeName") + "</a>";
            }
        }

        protected void searchLog(object sender, EventArgs e)
        {
        }

    }
}